
'''
项目介绍:商城类智能助手
商城Agent是一个基于大模型的智能助手,旨在为用户提供关于商品信息的智能查询和服务。该项目结合了自然语言处理与数据库查询技术,使得用户可以通过自然语言与系统交互,获取商品库存、规格等信息。
本项目采用Python语言编写,利用了SQLite作为后端数据库来存储商品信息,并通过一个基于Qwen3-4b模型的智能代理来处理用户的查询请求。系统设计考虑了在消费级硬件上的运行效率。

项目功能：
1. 智能对话：基于大模型实现自然语言的智能对话。
2. 数据库连接：能够连接到数据库，并根据商品数据回答用户关于商品库存和规格的问题。
3. 工具调用：能够调用外部工具，如数据库查询、网页搜索等。
4. 对话历史打印：输入“打印历史对话”可以查看之前的对话记录。
5. 自主退出：输入“退出”即可结束当前对话。
6. 支持多轮对话：具有短时记忆能力，支持连续多轮的对话交互。

本代码需要调用函数Connect_Sql.py中的函数query_by_product_name
Code by Zyy

2025.10.1更新
完善了agent调用工具的历史对话回传
By Zyy


2025.10.1 晚20:16更新
对工具调用进行封装
By Zyy

2025.10.1 晚21:28更新
开放模型对工具并行调用的能力
By Zyy
'''

from openai import OpenAI
import json 
import Connect_Sql
# 创建OpenAI对象
client = OpenAI(
    base_url='http://localhost:11434/v1/',
    api_key='zyy'
)
print('欢迎来到UpDownSeek商城')
# 创建消息列表
messages = [
  {'role':'system','content':'你是UpDownSeek商城助手，致力于为客户提供有用的信息和帮助。用中文回答客户问题。'},
]
# 定义查询函数调用的JSON Schema
Json_Schema = {
            'name':'query_by_product_name', #函数名称
            'description':'查询数据库来检索匹配包含指定产品名称的产品列表。此功能可用于帮助客户按名称查找产品，当用户询问某类产品还有吗，你们这边都有什么xx产品等，可以使用这个功能来查询是否有该产品', #函数描述
            'parameters':{ #函数参数
                'type':'object', #参数类型
                'properties':{ #参数名称
                    'product_name':{ #query_by_product_name函数的参数名称
                        'type':'string', #参数类型
                        'description':'你要要搜索的产品名称。' #参数描述
                    }
                },
                'required':['product_name'] #如果调用该函数的话，必须要上传该参数
            }
  }
# 创建工具列表
tools = [{
  'type':'function',
  'function':Json_Schema
}]
while True:
  # 获取用户输入
  prompt = input('用户输入：')
  # 打印历史对话
  if prompt.lower() in ['打印历史对话']:
    print(messages)
    continue
  # 如果输入退出，则退出对话
  if prompt.lower() in ['退出','bye']:
    print('感谢您的支持，再见！')
    break
  # 如果输入其他内容，则进行对话
  else:
    messages.append({'role':'user','content':prompt})
    response = client.chat.completions.create(
      model='qwen3:4b',
      messages=messages,
      tools=tools,
      parallel_tool_calls=False, 
      )
    # 判断是否调用了工具
    if response.choices[0].message.tool_calls:  
      #对话回传，让模型知道调用了工具
      response = response.choices[0].message
      print('模型决定调用工具')
      #语法糖封装
      tool_calls_messages = []
      for tool_call in response.tool_calls:
        function_call = tool_call
        function_name = function_call.function.name
        function_args = json.loads(function_call.function.arguments)
        available_functions ={'query_by_product_name':Connect_Sql.query_by_product_name}
        function_to_call = available_functions[function_name]
        function_response = function_to_call(**function_args)
        tool_calls_messages.append(
          {
            'role':'tool',
            'name':function_name,
            'tool_call_id':tool_call.id,
            'content':str(function_response)
          }
        )
        for tool_call_message in tool_calls_messages:
          messages.append(tool_call_message)
      #再次生成回复
      response = client.chat.completions.create(
        model='qwen3:4b',
        messages=messages,
      )
  #无论是否调用工具，都要输出回复，并且添加到消息列表中   
  print(response.choices[0].message.content)
  messages.append({'role':'assistant','content':response.choices[0].message.content})
